﻿// MyProject.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
//公众号：程序员速成 ，内含一辈子都让你感激自己的优质视频教程，欢迎关注

#include <iostream>


#ifdef _DEBUG   //只在Debug（调试）模式下
#ifndef DEBUG_NEW
#define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__,__LINE__) //重新定义new运算符
#define new DEBUG_NEW
#endif
#endif

//#include <boost/type_index.hpp>
using namespace std;
//#pragma warning(disable : 4996) 

namespace _nmsp1
{	
	//图形相关类
	class graphic
	{
		//-------------单件类实现相关begin--------------
	private:
		graphic() {};
		graphic(const graphic& tmpobj);
		graphic& operator=(const graphic& tmpobj);
		~graphic() {};
	public:
		static graphic& getInstance()
		{
			static graphic instance;
			return instance;
		}
		//-------------单件类实现相关end--------------

	public:
		void display(bool enable) //是否全屏显示（true：是）
		{
			cout << "图形->是否全屏显示->" << enable << endl;
			//其他代码略......
		}
		void effect(bool enable) //是否开启特效（true：是）
		{
			cout << "图形->是否开启特效->" << enable << endl;			
		}
		void resolution(int index) //设置窗口分辨率
		{
			cout << "图形->分辨率设置选项->" << index << endl;
		}
		void antialiasing(bool enable)//是否开启抗锯齿（true：是）
		{
			cout << "图形->是否开启抗锯齿->" << enable << endl;
		}
		//....其他接口略
	};

	//声音相关类
	class sound
	{
		//-------------单件类实现相关begin--------------
	private:
		sound() {};
		sound(const sound& tmpobj);
		sound& operator=(const sound& tmpobj);
		~sound() {};
	public:
		static sound& getInstance()
		{
			static sound instance;
			return instance;
		}
		//-------------单件类实现相关end--------------

	public:
		void bgsound(bool enable) //是否开启背景声音（true：是）
		{
			cout << "声音->是否开启背景声音->" << enable << endl;
		}
		void envirsound(bool enable) //是否开启环境音效（true：是）
		{
			cout << "声音->是否开启环境音效->" << enable << endl;
		}
		void expsound(bool enable) //是否开启表情声音（true：是）
		{
			cout << "声音->是否开启表情声音->" << enable << endl;
		}
		void setvolume(int level) //音量大小设置（0-100）
		{
			cout << "声音->音量大小为->" << level << endl;
		}
		//......其他接口略
	};

	//语音聊天相关类
	class chatvoice
	{
		//-------------单件类实现相关begin--------------
	private:
		chatvoice() {};
		chatvoice(const chatvoice& tmpobj);
		chatvoice& operator=(const chatvoice& tmpobj);
		~chatvoice() {};
	public:
		static chatvoice& getInstance()
		{
			static chatvoice instance;
			return instance;
		}
		//-------------单件类实现相关end--------------

	public:		
		void micvolume(int level) //麦克风音量大小设置（0-100）
		{
			cout << "语音聊天->麦克风音量大小为->" << level << endl;
		}
		void micsens(int level) //麦克风灵敏度设置（0-100）
		{
			cout << "语音聊天->麦克风灵敏度为->" << level << endl;
		}
		void chatvolume(int level) //聊天音量设置（0-100）
		{
			cout << "语音聊天->聊天音量为->" << level << endl;
		}
		//......其他接口略
	};
	//-----------------------
	//扮演外观模式角色的类
	class conffacade
	{
		//-------------单件类实现相关begin--------------
	private:
		conffacade() {};
		conffacade(const conffacade& tmpobj);
		conffacade& operator=(const conffacade& tmpobj);
		~conffacade() {};
	public:
		static conffacade& getInstance()
		{
			static conffacade instance;
			return instance;
		}

	public:
		void LowConfComputer() //对于低配置电脑，只开启一些低配置选项
		{
			graphic& g_gp = graphic::getInstance();
			g_gp.display(true); //全屏耗费资源更低
			g_gp.effect(false);
			g_gp.resolution(2);
			g_gp.antialiasing(false);

			sound& g_snd = sound::getInstance();
			g_snd.bgsound(false);
			g_snd.envirsound(false);
			g_snd.expsound(false);
			g_snd.setvolume(15);

			chatvoice& g_cv = chatvoice::getInstance();
			g_cv.micvolume(20);
			g_cv.micsens(50);
			g_cv.chatvolume(60);
		}

		void HighConfComputer() //对于高配置电脑，能达到最好效果的项全部开启
		{
			graphic& g_gp = graphic::getInstance();
			g_gp.display(false); 
			g_gp.effect(true);
			g_gp.resolution(0);
			g_gp.antialiasing(true);

			sound& g_snd = sound::getInstance();
			g_snd.bgsound(true);
			g_snd.envirsound(true);
			g_snd.expsound(true);
			g_snd.setvolume(50);

			chatvoice& g_cv = chatvoice::getInstance();
			g_cv.micvolume(100);
			g_cv.micsens(100);
			g_cv.chatvolume(100);
		}
	};
}
namespace _nmsp2
{
	//屏幕
	class Screen
	{
	public:
		void On()
		{
			cout << "屏幕打开了!" << endl;
		}
		void Off()
		{
			cout << "屏幕关闭了!" << endl;
		}
	};

	//灯光
	class Light
	{
	public:
		void On()
		{
			cout << "灯光打开了!" << endl;
		}
		void Off()
		{
			cout << "灯光关闭了!" << endl;
		}
	};

	//音箱
	class Speaker
	{
	public:
		void On()
		{
			cout << "音箱打开了!" << endl;
		}
		void Off()
		{
			cout << "音箱关闭了!" << endl;
		}
	};

	//DVD播放器
	class DvdPlayer
	{
	public:
		void On()
		{
			cout << "DVD播放器打开了!" << endl;
		}
		void Off()
		{
			cout << "DVD播放器关闭了!" << endl;
		}
	};

	//游戏机
	class PlayerStation
	{
	public:
		void On()
		{
			cout << "游戏机打开了!" << endl;
		}
		void Off()
		{
			cout << "游戏机关闭了!" << endl;
		}
	};

	//-----------------------
	//家庭影院外观模式类
	class HomeTheaterFacade
	{
	public:
		void WatchMovie() //看电影
		{
			//屏幕打开，灯光熄灭，音箱打开，DVD播放器打开，游戏机关闭
			scnobj.On();
			lgobj.Off();
			spkobj.On();
			dpobj.On();
			psobj.Off();
		}

		void PlayGame() //玩游戏
		{
			//屏幕打开，灯光打开，音箱打开，DVD播放器关闭，游戏机打开
			scnobj.On();
			lgobj.On();
			spkobj.On();
			dpobj.Off();
			psobj.On();
		}

	private:
		Screen scnobj;
		Light lgobj;
		Speaker spkobj;
		DvdPlayer dpobj;
		PlayerStation psobj;
	};
}

int main()
{
	_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);//程序退出时检测内存泄漏并显示到“输出”窗口
	
	//第8章 外观（facade）模式:门面模式，结构型模式。目的：隔离接口——中间层。迪米特法则
	//（1）一个配置相关的范例
	//（2）引入外观（facade）模式
	//graphic、sound、chatvoice——业务类 conffacade
	//外观模式强调的是一种程序设计思想
	//外观模式体现了面向对象程序设计的一个原则——迪米特法则（Law of Demeter，简称LoD）。
	     //得墨忒耳法则或者最小知识原则（Least Knowledge Principle，简称LKP）：
	       //一个对象应该对其他对象尽可能少的了解，从而降低各个对象之间的耦合，提高系统可维护性。
	//外观模式包含2种角色
	//a)Facade（外观角色）：conffacade
	//b)Subsystem（子系统角色）：graphic、sound、chatvoice——业务类
	
	//外观设计模式的定义（实现意图）：提供了一个统一的接口，用来访问子系统中的一群接口。外观定义了一个高层接口，让子系统更容易使用。
	//外观模式为客户端和子系统之间提供了一种简化的交互渠道但是 并没有为子系统增加新的行为。如果希望增加新行为，应该通过修改子系统角色来实现。
	//（3）另一个外观模式的范例
	//家庭影院外观模式类：HomeTheaterFacade,电器设备关联
	//a)屏幕Screen；b)灯光Light；c)音箱Speaker；d)DVD播放器DvdPlayer；e)游戏机PlayerStation。
	//提供两个接口：
	//a)看电影模式（WatchMovie）：屏幕打开，灯光熄灭，音箱打开，DVD播放器打开，游戏机关闭。
	//b)玩游戏模式（PlayGame）：屏幕打开，灯光打开，音箱打开，DVD播放器关闭，游戏机打开。






	/*
	_nmsp1::graphic& g_gp = _nmsp1::graphic::getInstance();
	g_gp.display(false);
	g_gp.effect(true);
	g_gp.resolution(2);
	g_gp.antialiasing(false);

	cout << "---------------" << endl;
	_nmsp1::sound& g_snd = _nmsp1::sound::getInstance();
	g_snd.setvolume(80);
	g_snd.envirsound(true);
	g_snd.bgsound(false);

	cout << "---------------" << endl;
	_nmsp1::chatvoice& g_cv = _nmsp1::chatvoice::getInstance();
	g_cv.chatvolume(70);
	g_cv.micsens(65);
	*/

	/*
	_nmsp1::conffacade& g_cffde = _nmsp1::conffacade::getInstance();
	cout << "低配置电脑，调用LowConfComputer接口" << endl;
	g_cffde.LowConfComputer();


	cout << "---------------------------" << endl;
	cout << "高配置电脑，调用HighConfComputer接口" << endl;
	g_cffde.HighConfComputer();
	*/

	_nmsp2::HomeTheaterFacade htfacobj;
	cout << "开始看电影----------------" << endl;
	htfacobj.WatchMovie();


	cout << "开始玩游戏----------------" << endl;
	htfacobj.PlayGame();
	
	return 0;
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件

